/**
 * Copyright (c) 2012, Brent Mucci
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, 
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice, 
 *    this list of conditions and the following disclaimer in the documentation 
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **/

#include "mcl_bitstream_decoder.hpp"

using namespace mcl;

unsigned int BitstreamDecoder::read_bits_ue()
{
	unsigned int expGolombSuffix = 1;
	unsigned char leadingZeroBits,
		numZeros;
	// The maximum number of leading 0 bits, that include the terminating 1, is 32.
	for(numZeros = 0; numZeros < sizeof(unsigned int) << 3; numZeros++)
	{
		leadingZeroBits = super::read_bits(1);
		if(leadingZeroBits)
		{
			break;
		}
	}
	// If there are no leading 0s then return 0 (should actually throw an exception)
	if(!numZeros) return 0;
	// expGolombSuffix contains a 1 which will be a leading 1 once shifted, this is to form a binary pattern found in unsigned exp golomb decoding.
	expGolombSuffix = expGolombSuffix << numZeros;
	expGolombSuffix |= super::read_bits(numZeros);

	// Decode the suffix, do this by subtracting 1 from the terminating 1 followed by the suffix (this is a decode pattern).
	return expGolombSuffix - 1;
}

// Code cloning is acceptable to prevent additional stacking.
signed int BitstreamDecoder::read_bits_se()
{
	unsigned int expGolombSuffix = 1, codeNum, elementReturnValue;
	unsigned char leadingZeroBits,
		numZeros;
	// The maximum number of leading 0 bits, that include the terminating 1, is 32.
	for(numZeros = 0; numZeros < sizeof(unsigned int) << 3; numZeros++)
	{
		leadingZeroBits = super::read_bits(1);
		if(leadingZeroBits)
		{
			break;
		}
	}
	// If there are no leading 0s then return 0 (should actually throw an exception)
	if(!numZeros) return 0;
	// expGolombSuffix contains a 1 which will be a leading 1 once shifted, this is to form a binary pattern found in unsigned exp golomb decoding.
	expGolombSuffix = expGolombSuffix << numZeros;
	expGolombSuffix |= super::read_bits(numZeros);
	// Decode the suffix, do this by subtracting 1 from the terminating 1 followed by the suffix (this is a decode pattern).
	codeNum = expGolombSuffix - 1;
	// Convert the code num into its partial return value [(codeNum / 2) = codeNum >> 1]
	elementReturnValue = (codeNum >> 1);
	// Apply a ceiling procedure, if necessary
	elementReturnValue += (codeNum & 1);
	// Apply the sign of the number, if applicable: (-1)*exp(codeNum + 1) = (codeNum ^ 1) << ((sizeof(unsigned int) << 3) - 1)
	return elementReturnValue | ((codeNum ^ 1) << ((sizeof(unsigned int) << 3) - 1));
}